package com.example.tagsdemo.utils.generator;

import com.example.tagsdemo.dto.GeneratorDTO;
import com.example.tagsdemo.entity.DBTableColumns;
import com.example.tagsdemo.utils.SerialVersionUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.io.*;
import java.util.Date;
import java.util.List;

@Slf4j
public class PLUSFileUtils {

    private static final String TEMPLATE_BASE_PATH = "\\src\\main\\java\\com\\example\\tagsdemo\\template\\plus\\basedata.txt";
    private static final String TEMPLATE_ENTITY_PATH = "\\src\\main\\java\\com\\example\\tagsdemo\\template\\plus\\entity.txt";
    private static final String TEMPLATE_SERVICE_PATH = "\\src\\main\\java\\com\\example\\tagsdemo\\template\\plus\\service.txt";
    private static final String TEMPLATE_SERVICEIMPL_PATH = "\\src\\main\\java\\com\\example\\tagsdemo\\template\\plus\\serviceimpl.txt";
    private static final String TEMPLATE_DAO_PATH = "\\src\\main\\java\\com\\example\\tagsdemo\\template\\plus\\mapper.txt";
    private static final String TEMPLATE_XML_PATH = "\\src\\main\\java\\com\\example\\tagsdemo\\template\\plus\\xml.txt";


    private static final String ENTITY_PATH = "com.example.tagsdemo.entity";

    private static final String ENTITY_PATH_COMMON = "\\src\\main\\java";
    private static final String EXTENDS = " extends BaseData ";


    private static final String DATE_FORMAT = "yyyy-MM-dd";


    /**
     * 下划线命名转驼峰命名
     *
     * @param underscore
     * @return
     */
    public static String underscoreToCamelCase(String underscore) {
        String[] ss = underscore.split("_");
        if (ss.length == 1) {
            return underscore;
        }

        StringBuffer sb = new StringBuffer();
        sb.append(ss[0]);
        for (int i = 1; i < ss.length; i++) {
            sb.append(upperFirstCase(ss[i]));
        }

        return sb.toString();
    }

    /**
     * 首字母 转大写
     *
     * @param str
     * @return
     */
    private static String upperFirstCase(String str) {
        char[] chars = str.toCharArray();
        chars[0] -= 32;
        return String.valueOf(chars);
    }

    public static void readString(String table_name, List<DBTableColumns> columnsList) {
        String workPath = System.getProperty("user.dir");
//        readString( table_name, workPath,ENTITY_PATH,true,null, columnsList);
    }

    public static void readString(String table_name,String tableRemarks, GeneratorDTO dto,List<DBTableColumns> columnsList,String idType) {
        readEntity( table_name, tableRemarks,dto,columnsList);
        writerBaseData(dto.getWorkPath(),dto.getEntityPath());
        readService(table_name,dto);
        readServiceImpl(table_name,tableRemarks,dto);
        readMapper(table_name,dto,idType);
    }

    public static void readEntity(String table_name,String tableRemarks,GeneratorDTO dto,List<DBTableColumns> columnsList) {
        int len = 0;
        StringBuffer str = new StringBuffer("");
        String property = System.getProperty("user.dir");
        File file = new File(property + TEMPLATE_ENTITY_PATH);
        String className = upperFirstCase(underscoreToCamelCase(table_name));
        try {
            FileInputStream is = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader in = new BufferedReader(isr);
            String line = null;
            while ((line = in.readLine()) != null) {
                if (StringUtils.contains(line, "${package}")) {
                    line = StringUtils.replace(line, "${package}", dto.getEntityPath());
                }

                if (StringUtils.contains(line, "${remarks}")) {
                    line = StringUtils.replace(line, "${remarks}", tableRemarks);
                }

                if (StringUtils.contains(line, "${author}")) {
                    line = StringUtils.replace(line, "${author}", dto.getAuthor());
                }

                if (StringUtils.contains(line, "${date}")) {
                    line = StringUtils.replace(line, "${date}", DateFormatUtils.format(new Date(),DATE_FORMAT));
                }

                if (StringUtils.contains(line, "${tableName}")) {
                    line = StringUtils.replace(line, "${tableName}", table_name);
                }
                if (StringUtils.contains(line, "${className}")) {
                    line = StringUtils.replace(line, "${className}", className);
                }

                if (StringUtils.contains(line, "${UID}")) {
                    line = StringUtils.replace(line, "${UID}", SerialVersionUIDUtil.getUID());
                }

                if (StringUtils.contains(line, "${content}")) {
                    StringBuffer sb = new StringBuffer();
                    for (DBTableColumns c : columnsList) {

                        String columnName = underscoreToCamelCase(c.getColumnName());
                        String typeName =c.getTypeName();
                        String remarks =c.getRemarks();

                        if (StringUtils.equalsIgnoreCase(columnName, "id") || StringUtils.equalsIgnoreCase(columnName, "create_time")
                                || StringUtils.equalsIgnoreCase(columnName, "update_time")) {
                            if (!dto.getIsExtends()) {
                                append(sb,columnName,typeName,remarks);
                            }else{
                                continue;
                            }
                        }else{
                            append(sb,columnName,typeName,remarks);
                        }
                        line = sb.toString();
                    }
                }
                str.append(line);
                str.append("\r\n");

                len++;
            }
            in.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        writerString(className, str.toString(), dto.getWorkPath(), entityPathConvert(dto.getEntityPath()), ".java");
    }

    public static void readService(String table_name,GeneratorDTO dto) {
        int len = 0;
        StringBuffer str = new StringBuffer("");
        String property = System.getProperty("user.dir");
        File file = new File(property + TEMPLATE_SERVICE_PATH);
        String className = upperFirstCase(underscoreToCamelCase(table_name));
        String serviceName =  "I" + className + "Service";
        try {
            FileInputStream is = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader in = new BufferedReader(isr);
            String line = null;
            while ((line = in.readLine()) != null) {

                if (StringUtils.contains(line, "${package}")) {
                    line = StringUtils.replace(line, "${package}", dto.getServicePath());
                }

                if (StringUtils.contains(line, " ${entityPath}")) {
                    line = StringUtils.replace(line, " ${entityPath}", (dto.getEntityPath() + "." + className));
                }

                if (StringUtils.contains(line, "${className}")) {
                    line = StringUtils.replace(line, "${className}",serviceName);
                }

                if (StringUtils.contains(line, "${entityName}")) {
                    line = StringUtils.replace(line, "${entityName}",className);
                }

                str.append(line);
                str.append("\r\n");
                len++;
            }
            in.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        writerString(serviceName, str.toString(), dto.getWorkPath(), entityPathConvert(dto.getServicePath()),".java");
    }

    public static void readServiceImpl(String table_name,String tableRemarks,GeneratorDTO dto) {
        int len = 0;
        StringBuffer str = new StringBuffer("");
        String property = System.getProperty("user.dir");
        File file = new File(property + TEMPLATE_SERVICEIMPL_PATH);
        String className = upperFirstCase(underscoreToCamelCase(table_name));
        String serviceImplName = "I" + className + "ServiceImpl";
        try {
            FileInputStream is = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader in = new BufferedReader(isr);
            String line = null;
            while ((line = in.readLine()) != null) {

                if (StringUtils.contains(line, "${package}")) {
                    line = StringUtils.replace(line, "${package}", (dto.getServicePath() + ".impl"));
                }

                if (StringUtils.contains(line, " ${daoPath}")) {
                    line = StringUtils.replace(line, " ${daoPath}", (dto.getDaoPath() + "." + className  + "Mapper") );
                }

                if (StringUtils.contains(line, " ${entityPath}")) {
                    line = StringUtils.replace(line, " ${entityPath}",  (dto.getEntityPath() + "." + className));
                }

                String serviceName = "I" + className + "Service";
                if (StringUtils.contains(line, " ${servicePath}")) {
                    line = StringUtils.replace(line, " ${servicePath}", (dto.getServicePath() + "." + serviceName)  );
                }

                if (StringUtils.contains(line, "${remarks}")) {
                    line = StringUtils.replace(line, "${remarks}", tableRemarks);
                }

                if (StringUtils.contains(line, "${author}")) {
                    line = StringUtils.replace(line, "${author}", dto.getAuthor());
                }

                if (StringUtils.contains(line, "${date}")) {
                    line = StringUtils.replace(line, "${date}", DateFormatUtils.format(new Date(),DATE_FORMAT));
                }


                if (StringUtils.contains(line, "${serviceImplName}")) {
                    line = StringUtils.replace(line, "${serviceImplName}", serviceImplName);
                }

                if (StringUtils.contains(line, "${mapperName}")) {
                    line = StringUtils.replace(line, "${mapperName}",className + "Mapper");
                }

                if (StringUtils.contains(line, "${entityName}")) {
                    line = StringUtils.replace(line, "${entityName}",className);
                }

                if (StringUtils.contains(line, "${serviceName}")) {
                    line = StringUtils.replace(line, "${serviceName}",( "I"  + className + "Service") );
                }

                str.append(line);
                str.append("\r\n");
                len++;
            }
            in.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        writerString(serviceImplName, str.toString(), dto.getWorkPath(), entityPathConvert(dto.getServicePath() + ".impl"),".java");
    }

    public static void readMapper(String table_name,GeneratorDTO dto,String idType) {
        int len = 0;
        StringBuffer str = new StringBuffer("");
        String property = System.getProperty("user.dir");
        File file = new File(property + TEMPLATE_DAO_PATH);
        String className = upperFirstCase(underscoreToCamelCase(table_name));
        String mapperName = className + "Mapper";
        try {
            FileInputStream is = new FileInputStream(file);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader in = new BufferedReader(isr);
            String line = null;
            while ((line = in.readLine()) != null) {

                if (StringUtils.contains(line, "${package}")) {
                    line = StringUtils.replace(line, "${package}", dto.getDaoPath());
                }

                if (StringUtils.contains(line, " ${entityPath}")) {
                    line = StringUtils.replace(line, " ${entityPath}",  (dto.getEntityPath() + "." + className));
                }

                if (StringUtils.contains(line, "${className}")) {
                    line = StringUtils.replace(line, "${className}",mapperName);
                }

                if (StringUtils.contains(line, "${entityName}")) {
                    line = StringUtils.replace(line, "${entityName}",className);
                }
                str.append(line);
                str.append("\r\n");
                len++;
            }
            in.close();
            is.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        writerString(mapperName, str.toString(), dto.getWorkPath(), entityPathConvert(dto.getDaoPath()),".java");
    }

    public static void readXML(String table_name,GeneratorDTO dto) {
    }

    public static void writerBaseData(String workPath,String entityPath) {

        String llPath= workPath + ENTITY_PATH_COMMON + entityPathConvert(entityPath);
        String filePath = llPath + "\\BaseData.java";
        File file = new File(llPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        File javaPath = new File(filePath);
        if (javaPath.exists()) {
            javaPath.delete();
        }
        try {

            int len = 0;
            StringBuffer str = new StringBuffer("");
            String property = System.getProperty("user.dir");
            File templeFile = new File(property + TEMPLATE_BASE_PATH);
            FileInputStream is = new FileInputStream(templeFile);
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader in = new BufferedReader(isr);
            String line = null;
            while ((line = in.readLine()) != null) {
                if (StringUtils.contains(line, "${package}")) {
                    line = StringUtils.replace(line, "${package}", entityPath);
                }
                str.append(line);
                str.append("\r\n");
                len++;
            }
            in.close();
            is.close();

            OutputStreamWriter oStreamWriter = new OutputStreamWriter(new FileOutputStream(javaPath), "utf-8");
            oStreamWriter.append(str);
            oStreamWriter.close();

        } catch (Exception e) {
            log.info("BaseData实体类生成失败");
        }

        log.info("BaseData实体类生成成功,路径{}", filePath);
    }


    private static void append(StringBuffer sb,String cloumnName,String typeName,String remarks) {
        sb.append("    //" + remarks + System.getProperty("line.separator"));
        if (StringUtils.equalsIgnoreCase(typeName, "int") ||
                StringUtils.equalsIgnoreCase(typeName, "tinyint") || StringUtils.equalsIgnoreCase(typeName, "smallint")) {
            sb.append("    private Integer " + cloumnName + ";");
        } else if (StringUtils.equalsIgnoreCase(typeName, "varchar") ||
                StringUtils.equalsIgnoreCase(typeName, "char") || StringUtils.equalsIgnoreCase(typeName, "blob") || StringUtils.equalsIgnoreCase(typeName, "text")) {
            sb.append("    private String " + cloumnName + ";");
        } else if (StringUtils.equalsIgnoreCase(typeName, "bigint")) {
            sb.append("    private Long " + cloumnName + ";");
        } else if (StringUtils.equalsIgnoreCase(typeName, "timestamp") ||
                StringUtils.equalsIgnoreCase(typeName, "date") || StringUtils.equalsIgnoreCase(typeName, "datetime")) {
            sb.append("    private Date " + cloumnName + ";");
        } else if (StringUtils.equalsIgnoreCase(typeName, "decimal")  ) {
            sb.append("    private BigDecimal " + cloumnName + ";");
        } else if (StringUtils.equalsIgnoreCase(typeName, "float")) {
            sb.append("    private Float " + cloumnName + ";");
        } else if (StringUtils.equalsIgnoreCase(typeName, "double")) {
            sb.append("    private Double " + cloumnName + ";");
        }else {
            sb.append("    private String " + cloumnName + ";");
        }
        sb.append(System.getProperty("line.separator"));
    }

    private static void writerString(String className, String data, String workPath, String entityPath,String suffix) {
        String llPath= workPath + ENTITY_PATH_COMMON + entityPath;
        String filePath = llPath + "\\" + className + suffix;
        File file = new File(llPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        File javaPath = new File(filePath);
        if (javaPath.exists()) {
            javaPath.delete();
        }
        try {
            OutputStreamWriter oStreamWriter = new OutputStreamWriter(new FileOutputStream(javaPath), "utf-8");
            oStreamWriter.append(data);
            oStreamWriter.close();
        } catch (Exception e) {
            log.info("{}实体类生成失败,路径{}", className, filePath);
        }
        log.info("{}实体类生成成功,路径{}", className, filePath);
    }

    private static String entityPathConvert(String entityPath) {
        return new StringBuffer("\\").append(StringUtils.replace(entityPath, ".", "\\")).toString();
    }

}
